// tslint:disable
import { EndPoint, BuildConfig } from './types';
import applyUrlWithPlaceholders from './applyUrlWithPlaceholders';
import request from './request';

const defaultConfigure = (options) => options;
const defaultAfterResolve = (result: any) => Promise.resolve(result);
const defaultAfterReject = (result: any) => Promise.reject(result);

export default function buildApi(endpoints: EndPoint, config: BuildConfig) {
  const {
    baseUrl,
    configureOptions = defaultConfigure,
    configureHeaders = defaultConfigure,
    afterResolve = defaultAfterResolve,
    afterReject = defaultAfterReject,
  } = config;

  console.log(baseUrl, configureOptions, configureHeaders, afterResolve, afterReject);

  return Object.keys(endpoints).reduce((acc: any, key: string) => {
    const { path, required, method: normalizeArguments } = endpoints[key];

    // 处理一定需要传递的参数
    const requiredPlaceholders = required || [];
    const placeholderRegexp = /:([^\/$]+)/g;
    let match;
    while ((match = placeholderRegexp.exec(path))) {
      requiredPlaceholders.push(match[1]);
    }

    // 重新构造请求核心对象
    acc[key] = (...args) => {
      const normalizedArguments = normalizeArguments(...args);
      const placeholders = normalizedArguments.placeholders || {};
      const options = normalizedArguments.options || {};

      const augmentedOptions = {
        ...options,
        headers: configureHeaders({
          'Content-Type': 'application/json;charset=utf-8',
          Accept: '*/*',
          ...options.headers,
        }),
      };

      // 过滤出不在必传参数列表中的值
      const missingPlaceholders = requiredPlaceholders.filter((ckey) => !placeholders.hasOwnProperty(ckey));

      if (missingPlaceholders.length > 0) {
        const message = `The "${key}" API call cannot be performed. The following params were not specified: ${missingPlaceholders.join(
          ', ',
        )}`;
        // console.error(message);
        return Promise.reject(new Error(message)).catch((result: any) => {
          afterReject({ api: key, options, result });
        });
      }

      const url = baseUrl + applyUrlWithPlaceholders(path, placeholders);
      const req = request(url, configureOptions(augmentedOptions));

      const promise = req
        .then((data) => afterResolve({ api: key, options, data }))
        .catch((error) => Promise.reject(error))
        .catch((result: any) => {
          afterReject({ api: key, options, result });
        });

      return promise;
    };

    return acc;
  }, {});
}
